package api

import (
	"FeedXmh/app/dao"
	"FeedXmh/app/model"
	"FeedXmh/ext_biz"
	"FeedXmh/hub"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	mqtt "github.com/eclipse/paho.mqtt.golang"
	jwt "github.com/gogf/gf-jwt"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/encoding/gbinary"
	"github.com/gogf/gf/encoding/gjson"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/os/gtime"
	"github.com/gogf/gf/text/gstr"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/grand"
	"github.com/shopspring/decimal"
	"paco_toolkit/DMXFGW"
	"paco_toolkit/common"
	"time"
)

type gw struct {
}

var Gw = gw{}

func (*gw) GetStatus(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	addr := r.GetString("addr")
	sn := r.GetString("sn")

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		g.Log().Line().Debug("permission ok")

		if 1 > 2 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)

			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			//topic_s :=  fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			//topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			var data []byte
			var status DMXFGW.State
			size := binary.Size(status)
			g.Log().Line(true).Debugf("size=%d", size)
			msg := DMXFGW.CreateMsg(02, 0, uint32(size), data)
			g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(true).Info("GetStatus Gw recv from topic:" + msg.Topic())
				g.Log().Line(true).Info("GetStatus Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					if pack.C == 0x82 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 20; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						var c = pack.C
						if c == 0x82 {
							//状态
							status, err := DMXFGW.DecodeState(pack.Data)
							if err != nil {
								res["code"] = -1
								res["msg"] = err.Error()
							} else {
								f_status := DMXFGW.FormatState(status)
								//g.Log().Line().Debug(f_status)

								if sn == "" {
									//主机状态
									res["code"] = 0
									res["data"] = f_status
								} else {
									//从机状态
									nodeStates := f_status.NodeStates

									find := false
									online := false
									for k, s := range nodeStates {
										if f_status.NodeSN[k] == sn {
											find = true
											if gconv.Int(f_status.Enable[k]) > 0 && gconv.Int(f_status.Online[k]) > 0 {
												online = true
												res["code"] = 0
												res["data"] = s
											}
										}
									}

									if !find {
										res["code"] = -1
										res["msg"] = fmt.Sprintf("饲喂器 %s 不存在", sn)
									} else {
										if !online {
											res["code"] = -1
											res["msg"] = fmt.Sprintf("饲喂器 %s 离线", sn)
										}
									}
								}
							}
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = fmt.Sprintf("请求超时,终端设备%s可能已经离线", addr)
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) GetParam(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	addr := r.GetString("addr")

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 2 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)

			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			var data []byte
			var para DMXFGW.Para
			size := binary.Size(para)

			var npara DMXFGW.NodePara
			fsize := binary.Size(npara)
			g.Log().Line(true).Debugf("fsize=%d", fsize)
			g.Log().Line(true).Debugf("size=%d", size)
			msg := DMXFGW.CreateMsg(0, 0, uint32(size), data)
			g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(true).Infof("GetParam Gw recv from topic:%s", msg.Topic())
				g.Log().Line(true).Infof("GetParam Gw recv from addr:%s", addr)
				g.Log().Line(true).Infof("GetParam Gw recv from len:%d", len(msg.Payload()))
				//g.Log().Line(true).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					if pack.C == 0x80 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 100; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						var c = pack.C
						if c == 0x80 {
							//参数
							para, err := DMXFGW.DecodeParam(pack.Data)
							if err != nil {
								res["code"] = -1
								res["msg"] = err.Error()
							} else {
								fpara := DMXFGW.FormatParam(para)
								//g.Log().Line().Debug(fpara)

								res["code"] = 0
								res["data"] = fpara
							}
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = fmt.Sprintf("请求超时,终端设备%s可能已经离线", addr)
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) GetExParam(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	addr := r.GetString("addr")

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 2 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)

			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			var data []byte
			var para DMXFGW.ExPara
			size := binary.Size(para)

			g.Log().Line(true).Debugf("size=%d", size)
			msg := DMXFGW.CreateMsg(0x0A, 0, uint32(size), data)
			g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(true).Infof("GetParam Gw recv from topic:%s", msg.Topic())
				g.Log().Line(true).Infof("GetParam Gw recv from addr:%s", addr)
				g.Log().Line(true).Infof("GetParam Gw recv from len:%d", len(msg.Payload()))
				//g.Log().Line(true).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					if pack.C == 0x8A {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 100; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						var c = pack.C
						if c == 0x8A {
							//参数
							para, err := DMXFGW.DecodeExParam(pack.Data)
							if err != nil {
								res["code"] = -1
								res["msg"] = err.Error()
							} else {
								fpara := DMXFGW.FormatExParam(para)
								g.Log().Line().Debug(fpara)

								res["code"] = 0
								res["data"] = fpara
							}
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = fmt.Sprintf("请求超时,终端设备%s可能已经离线", addr)
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) SetParam(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	addr := r.GetString("addr")
	params := r.GetString("params")

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 2 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			fp := DMXFGW.FPara{}
			gjson.DecodeTo(params, &fp)
			//g.Log().Line().Debug(fp)

			buff := DMXFGW.EncodeParam(&fp)

			var data []byte
			_begin := common.GetStructFieldOffset(DMXFGW.Para{}, "Passwd")
			_end := common.GetStructFieldOffset(DMXFGW.Para{}, "NodeEn")
			_len := _end - _begin
			g.Log().Line(false).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			data = append(data, buff[_begin:_end]...)

			//data = append(data, buff...)
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x01, 0, size, data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x81 && Addr == 0x00 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 20; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						if pack.Data[0] == 0x00 {
							res["code"] = 0
							res["msg"] = "设置成功"
						} else {
							res["code"] = -1
							res["msg"] = "设置失败"
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) SetExParam(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	params := gconv.String(p["params"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 2 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			fp := DMXFGW.ExFPara{}
			gjson.DecodeTo(params, &fp)
			//g.Log().Line().Debug(fp)

			buff := DMXFGW.EncodeExParam(&fp)

			var data []byte
			_begin := common.GetStructFieldOffset(DMXFGW.ExPara{}, "EnMaxNode")
			_end := common.GetStructFieldOffset(DMXFGW.ExPara{}, "Rev")
			_len := _end - _begin
			g.Log().Line(false).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			data = append(data, buff[_begin:_end]...)

			//data = append(data, buff...)
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x0B, uint32(_begin), size, data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					//Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x8B {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 20; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						if pack.Data[0] == 0x00 {
							res["code"] = 0
							res["msg"] = "设置成功"
						} else {
							res["code"] = -1
							res["msg"] = "设置失败"
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) SetExParamName(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	SiteName := gconv.String(p["SiteName"])
	HouseName := gconv.String(p["HouseName"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 2 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			fp := DMXFGW.ExFPara{}
			fp.HouseName = HouseName
			fp.SiteName = SiteName

			buff := DMXFGW.EncodeExParam(&fp)

			var data []byte
			_begin := common.GetStructFieldOffset(DMXFGW.ExPara{}, "SiteName")
			_end := common.GetStructFieldOffset(DMXFGW.ExPara{}, "Rev")
			_len := _end - _begin
			g.Log().Line(false).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			data = append(data, buff[_begin:_end]...)

			//data = append(data, buff...)
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x0B, uint32(_begin), size, data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					//Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x8B {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 20; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						if pack.Data[0] == 0x00 {
							res["code"] = 0
							res["msg"] = "设置成功"
						} else {
							res["code"] = -1
							res["msg"] = "设置失败"
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) SetExParamLimit(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	EnMaxNode := gconv.String(p["EnMaxNode"])
	MaxNode := gconv.String(p["MaxNode"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 2 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			fp := DMXFGW.ExFPara{}
			fp.EnMaxNode = EnMaxNode
			fp.MaxNode = MaxNode

			buff := DMXFGW.EncodeExParam(&fp)

			var data []byte
			_begin := common.GetStructFieldOffset(DMXFGW.ExPara{}, "EnMaxNode")
			_end := common.GetStructFieldOffset(DMXFGW.ExPara{}, "SiteName")
			_len := _end - _begin
			g.Log().Line(false).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			data = append(data, buff[_begin:_end]...)

			//data = append(data, buff...)
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x0B, uint32(_begin), size, data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					//Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x8B {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 20; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						if pack.Data[0] == 0x00 {
							res["code"] = 0
							res["msg"] = "设置成功"
						} else {
							res["code"] = -1
							res["msg"] = "设置失败"
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) SetNodeParam(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := gconv.Int(p["enable"])
	params := gconv.String(p["params"])
	feed_plan_id := gconv.Int(p["feed_plan_id"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path

	log := gdb.Map{}
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)

			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			fp := DMXFGW.FNodePara{}
			gjson.DecodeTo(params, &fp)
			//g.Log().Line().Debug(fp)

			sn := dao.GetSnByAddrTn(addr, tn)

			log = gdb.Map{
				"userid":       userid,
				"addr":         addr,
				"tn":           tn,
				"sn":           sn,
				"feed_plan_id": feed_plan_id,
				"para":         params,
				"res":          "",
			}

			buff := DMXFGW.EncodeNodeParam(&fp)
			pid := gbinary.LeEncodeUint32(DMXFGW.PID)
			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Sn")
			_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Crc16")

			_offset := common.GetStructFieldOffset(DMXFGW.NodePara{}, "La_rev")
			g.Log().Line(true).Debugf("La_rev offset = %d", _offset)

			var buff_calc_crc16 []byte
			buff_calc_crc16 = append(buff_calc_crc16, pid...)
			buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			crc16 := common.CheckSum(buff_calc_crc16)
			crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, buff[_begin:_end]...)
			data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x05, 0, size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x85 && Addr == 0x00 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								time.Sleep(1 * time.Second)
								//设置成功，保存方案，保存参数变更记录
								items, err := dao.T_hzfgw_node_para.GetList(fmt.Sprintf(" addr='%s' and tn=%d", addr, tn))
								if err != nil {
									g.Log().Line(true).Error(err)
								} else {
									if len(items) > 0 {
										item := items[0]
										item["data"] = params
										if feed_plan_id > 0 {
											item["feed_plan_id"] = feed_plan_id
										}
										_, err = dao.T_hzfgw_node_para.Save(item)
										if err != nil {
											g.Log().Line(true).Error(err)
										} else {
											g.Log().Line(true).Debugf("update T_hzfgw_node_para addr='%s' sn=%s feed_plan_id=%d ok", addr, gconv.String(item["sn"]), feed_plan_id)
										}

										//old_data := gconv.String(item["data"])
										new_data := params
										para_his := gdb.Map{
											"feed_plan_id": feed_plan_id,
											"addr":         addr,
											"sn":           gconv.String(item["sn"]),
											//"old_data":    old_data,
											"new_data":    new_data,
											"his_date":    gtime.Now(),
											"update_user": userid,
										}

										_, err = dao.T_hzfgw_node_para_his.Save(para_his)
										if err != nil {
											g.Log().Line(true).Error(err)
										} else {
											g.Log().Line(true).Debugf("add t_hzfgw_node_para_his addr='%s' sn=%s ok", addr, gconv.String(item["sn"]))
										}
									}
								}
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	log["res"] = res["msg"]
	dao.T_op_log_set_para.Save(log)
	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) SetNodeFgParam(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := gconv.Int(p["enable"])
	params := gconv.String(p["params"])
	feed_plan_id := gconv.Int(p["feed_plan_id"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path

	log := gdb.Map{}
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)

			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			fp := DMXFGW.FNodeFgPara{}
			gjson.DecodeTo(params, &fp)
			//g.Log().Line().Debug(fp)

			sn := dao.GetSnByAddrTn(addr, tn)

			log = gdb.Map{
				"userid":       userid,
				"addr":         addr,
				"tn":           tn,
				"sn":           sn,
				"feed_plan_id": feed_plan_id,
				"para":         params,
				"res":          "",
			}

			buff := DMXFGW.EncodeNodeFgParam(&fp)
			pid := gbinary.LeEncodeUint32(DMXFGW.PID)
			_begin := common.GetStructFieldOffset(DMXFGW.NodeFgPara{}, "Sn")
			_end := common.GetStructFieldOffset(DMXFGW.NodeFgPara{}, "Crc16")

			_offset := common.GetStructFieldOffset(DMXFGW.NodeFgPara{}, "La_rev")
			g.Log().Line(true).Debugf("La_rev offset = %d", _offset)

			var buff_calc_crc16 []byte
			buff_calc_crc16 = append(buff_calc_crc16, pid...)
			buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			crc16 := common.CheckSum(buff_calc_crc16)
			crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, buff[_begin:_end]...)
			data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x05, 0, size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x85 && Addr == 0x00 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								time.Sleep(1 * time.Second)
								//设置成功，保存方案，保存参数变更记录
								items, err := dao.T_hzfgw_node_para.GetList(fmt.Sprintf(" addr='%s' and tn=%d", addr, tn))
								if err != nil {
									g.Log().Line(true).Error(err)
								} else {
									if len(items) > 0 {
										item := items[0]
										item["data"] = params
										if feed_plan_id > 0 {
											item["feed_plan_id"] = feed_plan_id
										}
										_, err = dao.T_hzfgw_node_para.Save(item)
										if err != nil {
											g.Log().Line(true).Error(err)
										} else {
											g.Log().Line(true).Debugf("update T_hzfgw_node_para addr='%s' sn=%s feed_plan_id=%d ok", addr, gconv.String(item["sn"]), feed_plan_id)
										}

										//old_data := gconv.String(item["data"])
										new_data := params
										para_his := gdb.Map{
											"feed_plan_id": feed_plan_id,
											"addr":         addr,
											"sn":           gconv.String(item["sn"]),
											//"old_data":    old_data,
											"new_data":    new_data,
											"his_date":    gtime.Now(),
											"update_user": userid,
										}

										_, err = dao.T_hzfgw_node_para_his.Save(para_his)
										if err != nil {
											g.Log().Line(true).Error(err)
										} else {
											g.Log().Line(true).Debugf("add t_hzfgw_node_para_his addr='%s' sn=%s ok", addr, gconv.String(item["sn"]))
										}
									}
								}
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	log["res"] = res["msg"]
	dao.T_op_log_set_para.Save(log)
	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) ResetNodeParam(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := gconv.Int(p["enable"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
		if token := c.Connect(); token.Wait() && token.Error() != nil {
			//panic(token.Error())
			g.Log().Line(true).Error(token.Error().Error())
		}
		topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
		topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
		g.Log().Line(true).Debug(topic_s)

		//fp := DMXFGW.FNodePara{}
		//g.Log().Line().Debug(fp)

		//buff := DMXFGW.EncodeNodeParam(&fp)
		_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Sn")
		_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Crc16")
		_len := _end - _begin
		g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

		var data []byte
		data = append(data, uint8(tn))
		data = append(data, uint8(enable))
		//data = append(data, buff[_begin:_end]...)
		for i := 0; i < int(_len); i++ {
			data = append(data, 0)
		}
		data = append(data, 0) //crc16
		data = append(data, 0) //crc16
		size := uint32(len(data))
		msg := DMXFGW.CreateMsg(0x05, 0, size, data)
		g.Log().Line(true).Debugf("Gw send msg: % X", msg)

		// 订阅主题
		var iscallback bool
		var pack *DMXFGW.Pack
		var err error
		//var mqtt_msg mqtt.Message
		if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
			topic := msg.Topic()
			topic_arr := gstr.Split(topic, "/")
			addr := topic_arr[2]
			g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
			g.Log().Line(false).Println("Gw recv from addr:" + addr)
			g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
			//解析返回
			pack, err = DMXFGW.DecodePack(msg.Payload())
			if err == nil {
				Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
				if pack.C == 0x85 && Addr == 0x00 {
					iscallback = true
					//mqtt_msg = msg
				}
			} else {
				iscallback = true
			}

		}); token.Wait() && token.Error() != nil {
			fmt.Println(token.Error())
		}

		// 发布消息
		token := c.Publish(topic_s, 0, false, msg)
		token.Wait()

		for i := 0; i <= 200; i++ {
			if iscallback {
				//解析返回
				if err != nil {
					res["code"] = -1
					res["msg"] = err.Error()
				} else {
					_tn := pack.Data[0]
					_res := pack.Data[1]
					if int(_tn) == tn {
						if _res == 0 {
							//设置成功，保存方案，保存参数变更记录
							items, err := dao.T_hzfgw_node_para.GetList(fmt.Sprintf(" addr='%s' and tn=%d", addr, tn))
							if err != nil {
								g.Log().Line(true).Error(err)
							} else {
								if len(items) > 0 {
									/*item := items[0]
									item["feed_plan_id"] = feed_plan_id
									_, err = dao.T_hzfgw_node_para.Save(item)
									if err != nil {
										g.Log().Line(true).Error(err)
									} else {
										g.Log().Line(true).Debugf("update T_hzfgw_node_para addr='%s' sn=%s feed_plan_id=%s ok", addr, gconv.String(item["sn"]), feed_plan_id)
									}

									old_data := gconv.String(item["data"])
									new_data := params

									para_his := gdb.Map{
										"addr":        addr,
										"sn":          gconv.String(item["sn"]),
										"old_data":    old_data,
										"new_data":    new_data,
										"his_date":    gtime.Now(),
										"update_user": userid,
									}

									_, err = dao.T_hzfgw_node_para_his.Save(para_his)
									if err != nil {
										g.Log().Line(true).Error(err)
									} else {
										g.Log().Line(true).Debugf("add t_hzfgw_node_para_his addr='%s' sn=%s ok", addr, gconv.String(item["sn"]))
									}*/
								}
							}
							res["code"] = 0
							res["msg"] = "设置成功"
						} else {
							res["code"] = -1
							res["msg"] = "设置失败"
						}
					} else {
						res["code"] = -1
						res["msg"] = "设置失败:tn错误"
					}

				}
				break
			} else {
				//继续等待
				time.Sleep(100 * time.Millisecond)
			}
		}
		c.Disconnect(250)
		if !iscallback {
			res["code"] = -1
			res["msg"] = "请求超时,设备可能已经离线"
		}
	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) GetClock(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	addr := r.GetString("addr")

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)

			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			var data []byte
			size := 0
			msg := DMXFGW.CreateMsg(03, 0, uint32(size), data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x83 && Addr == 0 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 20; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						res["code"] = 0
						res["data"] = fmt.Sprintf("20%02X-%02X-%02X %02X:%02X:%02X", pack.Data[0], pack.Data[1], pack.Data[2], pack.Data[3], pack.Data[4], pack.Data[5])
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) SetClock(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	addr := r.GetString("addr")

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			//校时日期
			var datetime = gtime.Now().Format("ymdHis")
			clock, _ := hex.DecodeString(datetime)

			var data []byte
			data = append(data, clock...)
			size := len(data)
			msg := DMXFGW.CreateMsg(03, 0x01, uint32(size), data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x83 && Addr == 0x01 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 20; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						if pack.Data[0] == 0x00 {
							res["code"] = 0
							res["msg"] = "设置成功"
						} else {
							res["code"] = -1
							res["msg"] = "设置失败"
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) Update(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	addr := r.GetString("addr")
	filename := r.GetString("filename")

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 2 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			var data []byte
			//设置固件
			//host:=r.Request.Host
			//url:=fmt.Sprintf("http://%s/public/firmware/%s",host,filename)
			//url := fmt.Sprintf("http://192.168.0.114:9901/firmware/%s", filename)
			url := fmt.Sprintf("%s%s", g.Cfg().GetString("basic.firmware"), filename)
			//url:="http://120.79.248.26/files/"+filename
			g.Dump(url)
			data = append(data, gbinary.LeEncodeString(url)...)
			size := len(data)
			msg := DMXFGW.CreateMsg(03, 0x02, uint32(size), data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x83 && Addr == 0x02 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 50; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						if pack.Data[0] == 0x00 {
							res["code"] = 0
							res["msg"] = "固件下发成功"
						} else {
							res["code"] = -1
							res["msg"] = "固件下发失败"
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) UpdateNode(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	addr := r.GetString("addr")
	saddr := r.GetString("saddr")
	filename := r.GetString("filename")

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			var data []byte
			//设置固件
			_addr := gconv.Uint32(saddr)
			if _addr == 0 {
				data = append(data, 0x41)
				data = append(data, 0x27)
				data = append(data, 0x21)
				data = append(data, 0xF8)
			} else {
				data = append(data, gbinary.LeEncodeUint32(_addr)...)
			}

			//host:=r.Request.Host
			//url:=fmt.Sprintf("http://%s/public/firmware/%s",host,filename)
			url := fmt.Sprintf("%s%s", g.Cfg().GetString("basic.firmware"), filename)
			//url:="http://120.79.248.26/files/"+filename
			g.Dump(url)
			data = append(data, gbinary.LeEncodeString(url)...)
			size := len(data)
			msg := DMXFGW.CreateMsg(03, 0x03, uint32(size), data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x83 && Addr == 0x03 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 50; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						if pack.Data[0] == 0x00 {
							res["code"] = 0
							res["msg"] = "固件下发成功"
						} else {
							res["code"] = -1
							res["msg"] = "固件下发失败"
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// ClearRecord 清空终端记录
func (*gw) ClearRecord(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	addr := r.GetString("addr")

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
		if token := c.Connect(); token.Wait() && token.Error() != nil {
			//panic(token.Error())
			g.Log().Line(true).Error(token.Error().Error())
		}
		topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
		topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
		g.Log().Line(false).Debug(topic_s)

		var data []byte
		data = append(data, 0x27)
		data = append(data, 0x41)
		size := len(data)
		msg := DMXFGW.CreateMsg(03, 0x10, uint32(size), data)
		g.Log().Line(false).Debugf("Gw send msg: % X", msg)

		// 订阅主题
		var iscallback bool
		var pack *DMXFGW.Pack
		var err error
		//var mqtt_msg mqtt.Message
		if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
			topic := msg.Topic()
			topic_arr := gstr.Split(topic, "/")
			addr := topic_arr[2]
			g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
			g.Log().Line(false).Println("Gw recv from addr:" + addr)
			g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
			//解析返回
			pack, err = DMXFGW.DecodePack(msg.Payload())
			if err == nil {
				Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
				if pack.C == 0x83 && Addr == 0x10 {
					iscallback = true
					//mqtt_msg = msg
				}
			} else {
				iscallback = true
			}

		}); token.Wait() && token.Error() != nil {
			fmt.Println(token.Error())
		}

		// 发布消息
		token := c.Publish(topic_s, 0, false, msg)
		token.Wait()

		for i := 0; i <= 20; i++ {
			if iscallback {
				//解析返回
				if err != nil {
					res["code"] = -1
					res["msg"] = err.Error()
				} else {
					if pack.Data[0] == 0x00 {
						res["code"] = 0
						res["msg"] = "设置成功"
					} else {
						res["code"] = -1
						res["msg"] = "设置失败"
					}
				}
				break
			} else {
				//继续等待
				time.Sleep(100 * time.Millisecond)
			}
		}
		c.Disconnect(250)
		if !iscallback {
			res["code"] = -1
			res["msg"] = "请求超时,设备可能已经离线"
		}
	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// ManualFeed 手动下料下水
func (*gw) ManualFeed(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	feed := gconv.Int(p["feed"])
	water := gconv.Int(p["water"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			var data []byte
			feed_data := gbinary.LeEncodeUint16(uint16(feed))
			water_data := gbinary.LeEncodeUint16(uint16(water))
			data = append(data, uint8(tn))
			data = append(data, feed_data...)
			data = append(data, water_data...)
			size := len(data)
			msg := DMXFGW.CreateMsg(03, 0x06, uint32(size), data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x83 && Addr == 0x06 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						res["code"] = 0
						res["msg"] = "设置完成"
						item := g.Map{
							"feed_res":  pack.Data[0],
							"water_res": pack.Data[1],
						}
						res["data"] = item
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// ManualDeliverFeed 拉料接口
func (*gw) ManualDeliverFeed(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	_action := gconv.Int(p["action"])
	timer := gconv.Int(p["timer"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			var data []byte
			if _action > 0 {
				//拉料
				action_data := uint8(_action)
				timer_data := gbinary.LeEncodeUint16(uint16(timer))
				data = append(data, uint8(tn))
				data = append(data, action_data)
				data = append(data, 0x00) //保留字段
				data = append(data, timer_data...)
			} else {
				//停止拉料
				timer_data := gbinary.LeEncodeUint16(uint16(timer))
				data = append(data, uint8(tn))
				data = append(data, 0x00) //action
				data = append(data, 0x00) //保留字段
				data = append(data, timer_data...)
			}

			size := len(data)
			msg := DMXFGW.CreateMsg(03, 0x06, uint32(size), data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x83 && Addr == 0x06 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						res["code"] = 0
						res["msg"] = "设置完成"
						res["data"] = nil
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) ManualDeliverFeedBySn(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	p := r.GetFormMap()
	sn := gconv.String(p["sn"])
	_action := gconv.Int(p["action"])
	timer := gconv.Int(p["timer"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		//查询sn对应所处的的网关和tn
		list, err := dao.T_hzfgw_node_deliver.GetList(fmt.Sprintf("sn='%s'", sn))
		if err != nil {
			res["msg"] = err.Error()
			res["code"] = -1
		} else {
			if len(list) < 1 {
				res["msg"] = "拉料设备不存在"
				res["code"] = -1
			} else {
				item := list[0]
				addr := gconv.String(item["addr"])
				tn := gconv.Int(item["tn"])
				res_code, msg := hub.DeliverFeed(addr, sn, tn, timer, _action, fmt.Sprintf("用户%s手动拉料", userid))
				res["code"] = res_code
				res["msg"] = msg
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeSn 设置SN
func (*gw) SetNodeSn(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	sn := gconv.String(p["sn"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Sn")
			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			var t_buff = gbinary.LeEncodeUint32(gconv.Uint32(sn))

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff...)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								/*items, err := dao.T_hzfgw_node_para.GetList(fmt.Sprintf(" addr='%s' and tn=%d", addr, tn))
								if err != nil {
									g.Log().Line(true).Error(err)
								} else {
									item := items[0]
									item["data"] = params
								}*/
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeDay 设置日龄
func (*gw) SetNodeDay(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	day := gconv.String(p["day"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path

	sn := dao.GetSnByAddrTn(addr, tn)

	log := gdb.Map{
		"userid": userid,
		"addr":   addr,
		"tn":     tn,
		"sn":     sn,
		"day":    day,
		"res":    "",
	}

	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Gday")
			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			var t_buff = gbinary.LeEncodeUint16(uint16(gconv.Int(day)))

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff...)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								/*items, err := dao.T_hzfgw_node_para.GetList(fmt.Sprintf(" addr='%s' and tn=%d", addr, tn))
								if err != nil {
									g.Log().Line(true).Error(err)
								} else {
									item := items[0]
									item["data"] = params
								}*/
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	log["res"] = res["msg"]
	dao.T_op_log_set_day.Save(log)

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeHnum 设置栏位
func (*gw) SetNodeHnum(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	hnum := gconv.String(p["hnum"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")
			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			//var char = hnum[0]
			//char = char - 0x41
			//str := gconv.String(int(char)) + string(hnum[1:4])
			//fmt.Print(str)

			//hnum_val := uint16(gconv.Int(str))
			hnum_val := gconv.Int(gstr.TrimLeft(hnum, "0"))
			var t_buff = gbinary.LeEncodeUint16(uint16(hnum_val))

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff...)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeMode 设置模式
func (*gw) SetNodeMode(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	mode := gconv.String(p["mode"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Mode")
			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			var t_buff = uint8(gconv.Int(mode))

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodePassword 设置密码
func (*gw) SetNodePassword(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	passwd := gconv.String(p["passwd"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Passwd")
			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			var t_buff []byte
			arr1 := gbinary.LeEncodeUint32(uint32(gconv.Int(passwd)))
			t_buff = append(t_buff, arr1...)

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff...)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeMode 设置水压地址
func (*gw) SetNodeWpAddr(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	wp_addr := gconv.String(p["wp_addr"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)
			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "EnWater")

			var t_buff = uint8(gconv.Int(wp_addr))

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(true).Debug("Gw recv from topic:" + msg.Topic())
				g.Log().Line(true).Debug("Gw recv from addr:" + addr)
				g.Log().Line(true).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeCalcFeed 设置10圈出料(校准)
func (*gw) SetNodeCalcFeed(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	calFeed := gconv.String(p["calFeed"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path

	sn := dao.GetSnByAddrTn(addr, tn)

	log := gdb.Map{
		"userid": userid,
		"addr":   addr,
		"tn":     tn,
		"sn":     sn,
		"calc":   calFeed,
		"res":    "",
	}

	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "CalFeed")
			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			var t_buff = gbinary.LeEncodeUint16(uint16(gconv.Int(calFeed)))

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff...)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	log["res"] = res["msg"]
	dao.T_op_log_set_calc.Save(log)
	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeCalcWater 设置1水对应的脉冲数(校准)
func (*gw) SetNodeCalcWater(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	pulseWater := gconv.String(p["pulseWater"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "PulseWater")
			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			var t_buff = gbinary.LeEncodeUint16(uint16(gconv.Int(pulseWater)))

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff...)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeAD 设置AD值
func (*gw) SetNodeAD(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	calAD := gconv.String(p["calAD"])
	calADR := gconv.String(p["calADR"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "CalAD")
			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			var t_buff []byte
			arr1 := gbinary.LeEncodeUint16(uint16(gconv.Int(calAD)))
			arr2 := gbinary.LeEncodeUint16(uint16(gconv.Int(calADR)))
			t_buff = append(t_buff, arr1...)
			t_buff = append(t_buff, arr2...)

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff...)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeFeedOffset 设置增加减少饲喂量(饲喂量偏移值)
func (*gw) SetNodeFeedOffset(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	feedOffset := gconv.String(p["feedOffset"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "FeedOffset")
			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			var t_buff = uint8(gconv.Int(feedOffset))

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeWaterPTTO 水阀没有脉冲多久保护
func (*gw) SetNodeWaterPTTO(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1
	waterPTTO := gconv.Float32(p["waterPTTO"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			_begin := common.GetStructFieldOffset(DMXFGW.NodePara{}, "WaterPTTO")
			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			d := decimal.NewFromFloat32(waterPTTO)
			cd := d.Mul(decimal.NewFromInt32(100)).String()
			//var t_buff = gconv.Uint16(cd)

			var t_buff []byte
			arr1 := gbinary.LeEncodeUint16(uint16(gconv.Int(cd)))
			arr2 := gbinary.LeEncodeUint16(uint16(gconv.Int(cd)))
			t_buff = append(t_buff, arr1...)
			t_buff = append(t_buff, arr2...)

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff...)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// SetNodeWaterFeed 设置某个模式下某个日龄段的水料比
func (*gw) SetNodeWaterFeed(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	enable := 1

	mode := gconv.Int(p["mode"])
	arr_idx := gconv.Int(p["arr_idx"])
	water_feed := gconv.Float32(p["water_feed"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else if mode == 0 {
			res["code"] = -1
			res["msg"] = fmt.Sprintf("终端设备%s,当前停用无法设置水料比", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)
			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(true).Debug(topic_s)

			var _begin int64
			if mode == DMXFGW.FEED_MODE_PG {
				_begin = common.GetStructFieldOffset(DMXFGW.NodePara{}, "Pg_waterFeed") + int64(arr_idx)
			} else if mode == DMXFGW.FEED_MODE_LACTATION {
				_begin = common.GetStructFieldOffset(DMXFGW.NodePara{}, "La_waterFeed") + int64(arr_idx)
			} else if mode == DMXFGW.FEED_MODE_NURSE {
				_begin = common.GetStructFieldOffset(DMXFGW.NodePara{}, "Nr_waterFeed") + int64(arr_idx)
			} else if mode == DMXFGW.FEED_MODE_FAT {
				_begin = common.GetStructFieldOffset(DMXFGW.NodePara{}, "Fat_waterFeed") + int64(arr_idx)
			} else if mode == DMXFGW.FEED_MODE_TIMER {
				_begin = common.GetStructFieldOffset(DMXFGW.NodePara{}, "Tmr_waterFeed")
			}

			//_end := common.GetStructFieldOffset(DMXFGW.NodePara{}, "Hnum")

			//var buff_calc_crc16 []byte
			//buff_calc_crc16 = append(buff_calc_crc16, pid...)
			//buff_calc_crc16 = append(buff_calc_crc16, buff[_begin:_end]...)
			//crc16 := common.CheckSum(buff_calc_crc16)
			//crc16_bytes := gbinary.LeEncodeUint16(crc16)

			//_len := _end - _begin + 2 //2=crc16
			//g.Log().Line(true).Debugf("_begin=%d  _end =%d size=%d", _begin, _end, _len)

			d := decimal.NewFromFloat32(water_feed)
			cd := d.Mul(decimal.NewFromInt32(10)).String()
			var t_buff = gconv.Uint8(cd)

			var data []byte
			data = append(data, uint8(tn))
			data = append(data, uint8(enable))
			data = append(data, t_buff)
			//data = append(data, crc16_bytes...) //crc16
			size := uint32(len(data))
			msg := DMXFGW.CreateMsg(0x06, uint32(_begin), size, data)
			//g.Log().Line(true).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
				g.Log().Line(false).Println("Gw recv from addr:" + addr)
				//g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
					if pack.C == 0x86 && Addr == uint16(_begin) {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 200; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						_tn := pack.Data[0]
						_res := pack.Data[1]
						if int(_tn) == tn {
							if _res == 0 {
								res["code"] = 0
								res["msg"] = "设置成功"
							} else {
								res["code"] = -1
								res["msg"] = "设置失败"
							}
						} else {
							res["code"] = -1
							res["msg"] = "设置失败:tn错误"
						}

					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = "请求超时,设备可能已经离线"
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

// Qrcode 发生二维码给饲喂器
func (*gw) Qrcode(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}
	p := r.GetFormMap()
	addr := gconv.String(p["addr"])
	tn := gconv.Int(p["tn"])
	sn := gconv.Int(p["sn"])
	_type := gconv.String(p["type"])

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
		if token := c.Connect(); token.Wait() && token.Error() != nil {
			//panic(token.Error())
			g.Log().Line(true).Error(token.Error().Error())
		}
		topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
		topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
		g.Log().Line(false).Debug(topic_s)

		var inner_data []byte
		pre := ""
		if _type == "feed" || _type == "" {
			pre = "MXCSWQ"
		} else if _type == "fg" {
			pre = "MXCZLQ"
		}
		qr_buff := ext_biz.EncodeQrCode(uint32(sn), pre)
		sn_arr := gbinary.LeEncodeUint32(uint32(sn))

		inner_data = append(inner_data, qr_buff...)
		inner_data = append(inner_data, sn_arr...)
		sum := common.CalcSum8(inner_data)
		inner_data = append(inner_data, sum)

		var data []byte
		data = append(data, uint8(tn))
		data = append(data, inner_data...)

		size := len(data)
		msg := DMXFGW.CreateMsg(03, 0x07, uint32(size), data)
		g.Log().Line(false).Debugf("Gw send msg: % X,len=%d", msg, len(msg))

		// 订阅主题
		var iscallback bool
		var pack *DMXFGW.Pack
		var err error
		//var mqtt_msg mqtt.Message
		if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
			topic := msg.Topic()
			topic_arr := gstr.Split(topic, "/")
			addr := topic_arr[2]
			g.Log().Line(false).Println("Gw recv from topic:" + msg.Topic())
			g.Log().Line(false).Println("Gw recv from addr:" + addr)
			g.Log().Line(false).Debugf("Gw recv msg: % X", msg.Payload())
			//解析返回
			pack, err = DMXFGW.DecodePack(msg.Payload())
			if err == nil {
				Addr := gbinary.LeDecodeToUint16(pack.Addr[:])
				if pack.C == 0x83 && Addr == 0x07 {
					iscallback = true
					//mqtt_msg = msg
				}
			} else {
				iscallback = true
			}

		}); token.Wait() && token.Error() != nil {
			fmt.Println(token.Error())
		}

		// 发布消息
		token := c.Publish(topic_s, 0, false, msg)
		token.Wait()

		for i := 0; i <= 200; i++ {
			if iscallback {
				//解析返回
				if err != nil {
					res["code"] = -1
					res["msg"] = err.Error()
				} else {
					if pack.Data[0] == 0x00 {
						res["code"] = 0
						res["msg"] = "设置成功"
					} else {
						res["code"] = -1
						res["msg"] = "设置失败"
					}
				}
				break
			} else {
				//继续等待
				time.Sleep(100 * time.Millisecond)
			}
		}
		c.Disconnect(250)
		if !iscallback {
			res["code"] = -1
			res["msg"] = "请求超时,设备可能已经离线"
		}
	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) UpdateStatus(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	addr := r.GetString("addr")

	claims := jwt.ExtractClaims(r)
	userid := claims["userid"].(string)
	url := r.URL.Path
	if dao.CheckApiPermission(url, r.Method, userid) {
		g.Log().Line().Debug("permission ok")

		if 1 > 1 {
			g.Log().Line(true).Warningf("Gw %s busy...", addr)
			res["code"] = -1
			res["msg"] = fmt.Sprintf("请求失败,终端设备%s正忙", addr)
		} else {
			//model.ProcessDeviceList.PushBack(addr)
			//defer hub.RemoveProcessDeviceByAddr(addr)

			c := hub.CreateMqttClient("cid_Hub_"+grand.Digits(10), nil, nil)
			if token := c.Connect(); token.Wait() && token.Error() != nil {
				//panic(token.Error())
				g.Log().Line(true).Error(token.Error().Error())
			}
			topic_s := fmt.Sprintf("S/%s/%s", model.GW_MODE, addr)
			topic_p := fmt.Sprintf("P/%s/%s", model.GW_MODE, addr)
			g.Log().Line(false).Debug(topic_s)

			var data []byte
			var status DMXFGW.UpState
			size := binary.Size(status)
			g.Log().Line(true).Debugf("size=%d", size)
			msg := DMXFGW.CreateMsg(03, 0x08, uint32(size), data)
			g.Log().Line(false).Debugf("Gw send msg: % X", msg)

			// 订阅主题
			var iscallback bool
			var pack *DMXFGW.Pack
			var err error
			//var mqtt_msg mqtt.Message
			if token := c.Subscribe(topic_p, 0, func(c mqtt.Client, msg mqtt.Message) {
				topic := msg.Topic()
				topic_arr := gstr.Split(topic, "/")
				addr := topic_arr[2]
				g.Log().Line(true).Info("GetStatus Gw recv from topic:" + msg.Topic())
				g.Log().Line(true).Info("GetStatus Gw recv from addr:" + addr)
				g.Log().Line(true).Debugf("Gw recv msg: % X", msg.Payload())
				//解析返回
				pack, err = DMXFGW.DecodePack(msg.Payload())
				if err == nil {
					if pack.C == 0x83 {
						iscallback = true
						//mqtt_msg = msg
					}
				} else {
					iscallback = true
				}

			}); token.Wait() && token.Error() != nil {
				fmt.Println(token.Error())
			}

			// 发布消息
			token := c.Publish(topic_s, 0, false, msg)
			token.Wait()

			for i := 0; i <= 20; i++ {
				if iscallback {
					//解析返回
					if err != nil {
						res["code"] = -1
						res["msg"] = err.Error()
					} else {
						var c = pack.C
						if c == 0x83 {
							//状态
							status, err := DMXFGW.DecodeUpState(pack.Data)
							if err != nil {
								res["code"] = -1
								res["msg"] = err.Error()
							} else {
								res["code"] = 0
								res["data"] = status
							}
						}
					}
					break
				} else {
					//继续等待
					time.Sleep(100 * time.Millisecond)
				}
			}
			c.Disconnect(250)
			if !iscallback {
				res["code"] = -1
				res["msg"] = fmt.Sprintf("请求超时,终端设备%s可能已经离线", addr)
			}
		}

	} else {
		res["code"] = -1
		res["msg"] = "您没有该操作权限"
	}

	r.Response.WriteJson(res)
	r.ExitAll()
}

func (*gw) GetOnline(r *ghttp.Request) {
	res := g.Map{
		"code":  0,
		"msg":   "",
		"data":  "",
		"count": "",
	}

	clients_data, _ := hub.GetApiClients(gdb.Map{
		"_page":          1,
		"_limit":         100000,
		"_like_clientid": fmt.Sprintf("cid_%s_", model.GW_MODE),
	})
	res["data"] = clients_data
	res["count"] = len(clients_data)

	r.Response.WriteJson(res)
	r.ExitAll()
}
